package top.v5it.japi.plus.core.api;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Objects;

/**
 * 异常响应实体
 *
 * @author zhanpu
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class ErrorResult implements Serializable {

    private static final long serialVersionUID = 3832172379830886524L;

    /**
     * 状态码
     */
    @JsonIgnore
    private final int status;

    /**
     * 返回编码
     */
    @JsonProperty("return_code")
    private final String returnCode;

    /**
     * 错误描述
     */
    private final String message;

    /**
     * 错误请求uri
     */
    private Detail detail;

    /**
     * 错误
     *
     * @param resultStatusTemplate {@link ResultStatusTemplate}
     * @return {@link ErrorResult}
     */
    public static ErrorResult failure(ResultStatusTemplate resultStatusTemplate) {
        return failure(
                resultStatusTemplate.getStatus()
                , resultStatusTemplate.toString()
                , resultStatusTemplate.getMessage()
        );
    }

    /**
     * 错误
     *
     * @param resultStatusTemplate {@link ResultStatusTemplate}
     * @param message              消息说明，参考{@link ResultStatus#getMessage()}
     * @return {@link ErrorResult}
     */
    public static ErrorResult failure(ResultStatusTemplate resultStatusTemplate, final String message) {
        return failure(
                resultStatusTemplate.getStatus()
                , resultStatusTemplate.toString()
                , StrUtil.isNotBlank(message) ? message : resultStatusTemplate.getMessage()
        );
    }

    /**
     * 将一个object对象转换成{@link ErrorResult}，{@link ErrorResult}子类返回{@link ErrorResult}，否则返回null
     *
     * @param result 一个{@link ErrorResult}的子类入参
     * @return {@link ErrorResult}
     */
    public static ErrorResult of(Object result) {
        return Objects.nonNull(result) && result instanceof ErrorResult
                ? (ErrorResult) result
                : null;
    }

    /**
     * 自定义错误信息
     *
     * @param returnCode 编码，参考{@link ResultStatus#name()}
     * @param message    消息说明，参考{@link ResultStatus#getMessage()}
     * @return {@link ErrorResult}
     */
    public static ErrorResult failure(final String returnCode, final String message) {
        return failure(400, returnCode, message);
    }

    /**
     * 自定义错误信息
     *
     * @param status     状态码，参考{@link ResultStatus#getStatus()}
     * @param returnCode 编码，参考{@link ResultStatus#name()}
     * @param message    消息说明，参考{@link ResultStatus#getMessage()}
     * @return {@link ErrorResult}
     */
    public static ErrorResult failure(final int status, final String returnCode, final String message) {
        return new ErrorResult(status, returnCode, message);
    }

    @Data
    @EqualsAndHashCode(callSuper = false)
    @Accessors(chain = true)
    public static class Detail {

        private String field;
        private String value;
        private String issue;
    }
}
